/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package compilador.analisadorSintatico.comandos;

import compilador.analisadorLexico.*;
import compilador.analisadorSintatico.Producao;
import compilador.analisadorSintatico.TokenReader;
import compilador.analisadorSintatico.operacoes.EXP_INC;
import compilador.analisadorSintatico.simboloGramatical.NaoTerminal;
import compilador.analisadorSintatico.simboloGramatical.SimboloGramatical;
import compilador.analisadorSintatico.metodos.*;
import compilador.analisadorSintatico.simboloGramatical.Terminal;

/**
 * @author João Matos
 */
public class CMD_SEQUENCIAL extends Producao {

    @Override
    public SimboloGramatical derivar() throws Exception {

        TokenReader tokenReader = TokenReader.getInstance();
        Token t = tokenReader.seeCurrent();
        Token tnext = tokenReader.seeNext();
        Producao p = null;

        //<CMD_SEQUENCIAL> ::= <ATRIBUICAO> | <RETORNO> |  <CHAMADA_METODO> ';' | <EXP_INC> ;
        //<CHAMADA_METODO> 	{write, read}
        // <EXP_INC>	 { write, read,}


        if (t.getTokenClass().equals(TokenClass.PALAVRA_RESERVADA) && t.getAtributo().toString().equals("return")) {
            ((NaoTerminal) simbolo).add(new RETORNO().derivar());
            return simbolo;
        } else if (t.getAtributo().toString().equals("(") || t.getTokenClass().equals(TokenClass.NUMERO) || t.getAtributo().toString().equals("-")) {
            ((NaoTerminal) simbolo).add(new EXP_INC().derivar());
            return simbolo;
        } else if (t.getTokenClass().equals(TokenClass.IDENTIFICADOR)) {
            if (tnext.getAtributo().toString().equals("(")) {
                ((NaoTerminal) simbolo).add(new CHAMADA_METODO().derivar());
                t = tokenReader.consome();
                if (t.getAtributo().toString().equals(";")) {
                    ((NaoTerminal) simbolo).add(new Terminal(t));
                    return simbolo;
                } else {
                    erro("comando sequencial mal formado" +
                            "; esperado");
                    return simbolo;
                }

            } else if (tnext.getAtributo().equals(".")) {
                int i = 1;
                Token index = tokenReader.seeNext(i);
                while (!index.getAtributo().equals(";")) {
                    // verifica se incremento
                    if (index.getAtributo().equals("++") || index.getAtributo().equals("--")) {
                        ((NaoTerminal) simbolo).add(new EXP_INC().derivar());
                        if (tokenReader.seeCurrent().getAtributo().equals(";")){
                            ((NaoTerminal) simbolo).add(new Terminal(tokenReader.consome()));
                            return simbolo;
                        }
                        
                    } // verifica se atribuicao
                    else if (index.getAtributo().equals("=")) {
                        ((NaoTerminal) simbolo).add(new ATRIBUICAO().derivar());
                        return simbolo;
                    }
                    i++;
                    index = tokenReader.seeNext(i);
                }
                // erro caso finalize sem encontrar um dos dois nao terminais
                erro("Não foi possivel encontrar uma atribuição ou uma exp inc");
                return simbolo;
                
            } else if (tnext.getAtributo().equals("=")) {
                p = new ATRIBUICAO();
                ((NaoTerminal) simbolo).add(p.derivar());
                return simbolo;
            } else if (tnext.getAtributo().toString().equals("++") || tnext.getAtributo().toString().equals("--")) {
                ((NaoTerminal) simbolo).add(new EXP_INC().derivar());
                t = tokenReader.consome();
                if (t.getAtributo().toString().equals(";")) {
                    ((NaoTerminal) simbolo).add(new Terminal(t));
                    return simbolo;
                } else {
                    erro("comando sequencial mal formado" +
                            "; esperado");
                    return simbolo;
                }
            } else {
                erro("comando sequencial mal formado" +
                        "[ esperado");
                return simbolo;
            }
        } else if (t.getAtributo().toString().equals("write") || t.getAtributo().toString().equals("read")) {

            p = new CHAMADA_METODO();
            ((NaoTerminal) simbolo).add(p.derivar());
            t = tokenReader.consome();
            if (t.getAtributo().toString().equals(";")) {
                ((NaoTerminal) simbolo).add(new Terminal(t));
                return simbolo;
            } else {
                erro("comando sequencial mal formado" +
                        "; esperado");
                return simbolo;
            }
        } else {
            erro("comando sequencial mal formado" +
                    "write ou read esperado");
            return simbolo;
        }


    }

    @Override
    public void setSimbolo() {
        simbolo = new NaoTerminal("CMD_SEQUENCIAL");
    }
}
